package com.dries.security.core.authorize;

import com.dries.security.core.component.CustomSecurityFilter;
import com.dries.security.core.component.CustomSecurityService;
import com.dries.security.core.component.RestAuthenticationEntryPoint;
import com.dries.security.core.component.RestfulAccessDeniedHandler;
import com.dries.security.core.properties.SecurityCoreConstants;
import com.dries.security.core.properties.SecurityCoreProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @Description:
 * @Author ZSY
 * @createTime 2020/9/20 13:53
 */
@Slf4j
@Component
@Order(Integer.MIN_VALUE)
public class DriesAuthorizeConfigProvider implements AuthorizeConfigProvider {

    @Resource
    public SecurityCoreProperties coreProperties;
    @Autowired(required = false)
    private CustomSecurityService customSecurityService;
    @Resource
    private CustomSecurityFilter customSecurityFilter;
    @Resource
    private RestfulAccessDeniedHandler restfulAccessDeniedHandler;
    @Resource
    private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
    
    /**
     * @param config
     * @return 返回的boolean表示配置中是否有针对anyRequest的配置。在整个授权配置中，
     * 应该有且仅有一个针对anyRequest的配置，如果所有的实现都没有针对anyRequest的配置，
     * 系统会自动增加一个anyRequest().authenticated()的配置。如果有多个针对anyRequest
     * 的配置，则会抛出异常。
     */
    @Override
    public boolean config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config) throws Exception {

        config.antMatchers(HttpMethod.OPTIONS,
                SecurityCoreConstants.DEFAULT_ERROR_URL,
                SecurityCoreConstants.DEFAULT_UNAUTHENTICATION_URL,
                SecurityCoreConstants.DEFAULT_SIGN_IN_PROCESSING_URL_OPENID,
                SecurityCoreConstants.DEFAULT_LOGIN_PROCESSING_URL_MOBILE,
                SecurityCoreConstants.DEFAULT_VALIDATE_CODE_URL_PREFIX + "/*"
        ).permitAll();

        for (String url : coreProperties.getIgnoreUrls().getUrls()) {
            config.antMatchers(url).permitAll();
        }

        config
                .and()
                .exceptionHandling()
                .accessDeniedHandler(restfulAccessDeniedHandler)
                .authenticationEntryPoint(restAuthenticationEntryPoint);

        if (customSecurityService != null) {
            config.and().addFilterBefore(customSecurityFilter, FilterSecurityInterceptor.class);
        }

        return false;
    }
}
